清理和初始化
默认构造器
只要定义了一个构造器,编译器就不会帮我们自动创建默认构造器了。
this
1 | String a = new String(); |
如何确定调用类中的方法的对象是哪一个?
实际上,a.toString()的真实调用时这样的:String(a)。
编译器会暗自把“所操作的对象的引用”作为第一个参数传递给peel()。
使用this有什么用?
- 构造器中调用其它构造器只能使用this(参数),这时候的this的含义不表示对象的引用了。不能使用两次。
- 区别参数和成员对象。
- 返回当前的对象,this的类型是实际运行时类型。
注意:static方法不能使用this
垃圾回收
一般来说,JAVA中的GC可以帮我们回收无用对象占有的资源,但也有一些特殊情况:垃圾回收期只回收使用new关键字分配的内存,通过其他方式获取的“特殊”内存区域,GC不知道如何回收。
如何应对这种情况?
JAVA提供了finalize()方法,垃圾回收器在回收对象前会调用这个方法。
finalize()这和C++中的析构函数一样吗?
C++中的对象可以在栈中,也可以在堆中。在栈中的对象生命周期是当前方法的作用域,离开这个作用域“{}”,就会调用析构函数,并且回收内存。在堆中的对象(使用new)需要使用delete来销毁,并且在回收内存也会调用析构函数。那么这里有两点:
- 对象内存一定会被回收。
- 析构函数正常情况下都会被调用。
C++中没有被回收的内存会造成内存泄漏,一直到下次重启这部分占用的内存才会消除。
由此我们可以分析出java中的垃圾回收和finalize()的区别了:
- 对象不一定会被回收,即便是GC开始回收了。
- 因此finalize()也不一定会被调用,因此在finalize()中处理关闭资源等普通的清理操作是没有意义的。
和C++还有不一样的一点是,finalize()是不能被直接调用的。
那么finalize()有什么用呢?
我们说垃圾回收是和内存不足了有关的,那么也就意味着:
- 只有内存不足的时候才会调用finalize(),也就意味着,在finalize()中最好也是处理内存相关的清理操作,而不是关闭资源等普通的清理操作。
需要在finalize()里处理的内存清理操作是什么?
这种情况主要发生在“本地方法”的情况下,即在JAVA中调用了非JAVA的方法,这部分方法申请的内存需要使用free()来释放,因此在finalize()中调用free()方法。
初始化
变量在使用前必须初始化,否则会出现程序错误。
成员变量会有一个默认值,局部变量需要手动赋值。
初始化的顺序是怎样的?
感觉就是分为类的初始化和对象的初始化。
- 当首次调用静态方法,静态字段,构造器(可以看成静态方法)时,检查Class文件,若未发现,开始类初始化:加载.class文件,然后按顺序执行所有的静态初始化。
- 之后就不会再做类初始化了,当调用new()的时候执行对象的初始化:先在堆上分配空间,这块空间会被清零,也就是开始赋默认值,执行非静态的初始化。
- 执行构造器。
- 将引用指向这个地址(这一步有可能重排序)